#ifndef _BASE_MUTEX_H_
#define _BASE_MUTEX_H_

#include <exception>

#ifdef _POSIX_VERSION
#include <pthread.h>
#elif WIN32
#include "Windows.h"
#endif

namespace Maha
{
      namespace Base
      {

	      class CantCreateMutex : public std::exception
      	{
      	};

            class Mutex
            {
            public:
		      
		      Mutex() throw (CantCreateMutex&)
		      {
#ifdef _POSIX_VERSION
                        handle = initPthreadMutex();
#elif WIN32
                        LPSECURITY_ATTRIBUTES lpMutexAttributes = 0;
                        BOOL bInitialOwner = false;
                        LPCTSTR lpName = 0;
                  
                        handle = CreateMutex(lpMutexAttributes, bInitialOwner, lpName);

                        if (!handle)
                        {
                              throw (CantCreateMutex());
                        }
#endif	
                  }

                  void lock()
                  {
#ifdef _POSIX_VERSION
                        pthread_mutex_lock(&handle);
#elif WIN32
                        WaitForSingleObject(handle, INFINITE);
#endif
                  }

                  void unlock()
                  {
#ifdef _POSIX_VERSION
	                  pthread_mutex_unlock(&handle);
#elif WIN32
			      ReleaseMutex(handle);
#endif
		      }
		
		      ~Mutex()
		      {
#ifdef _POSIX_VERSION
#elif WIN32
			      CloseHandle(handle);
#endif
		      }

            private:

#ifdef _POSIX_VERSION
		      pthread_mutex_t initPthreadMutex()
		      {
                        pthread_mutex_t newHandle;;
                        pthread_mutexattr_t attr;
                        pthread_mutexattr_init(&attr);
                        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
                        pthread_mutex_init(&newHandle, &attr);
                        pthread_mutexattr_destroy(&attr);

                        // pthread_mutex_t newHandle = PTHREAD_MUTEX_INITIALIZER;
			      return newHandle;
		      }
#endif

	      private:
#ifdef _POSIX_VERSION
		      pthread_mutex_t handle;
#elif WIN32
		      HANDLE handle;
#endif
	      };
      } // Meta
} // Maha

#endif // _BASE_MUTEX_H_
